#ifndef _ELF_PARSER_H_
#define _ELF_PARSER_H_

#include "bitness.h"
#include "elf.h"
#include "file_structure.h"
#include "parser.h"

#include <array>
#include <filesystem>
#include <fstream>
#include <optional>
#include <type_traits>
#include <variant>
#include <vector>

namespace analyzer::posix
{

class elf_parser final : public parser
{
public:
    elf_parser(std::filesystem::path path);

    std::optional<file_structure> parse() override;

    using sections32 = std::vector<elf_section32>;
    using sections64 = std::vector<elf_section64>;
    using headers32 = std::vector<elf_program_header32>;
    using headers64 = std::vector<elf_program_header64>;
    using dynamic_sections32 = std::vector<elf_dynamic_section32>;
    using dynamic_sections64 = std::vector<elf_dynamic_section64>;

private:
    void read_ident();
    void read_header();
    void read_section_headers();
    void read_program_headers();
    void read_dynamic_sections(const size_t offset);

    bool is_elf() const noexcept;
    bool is_exec() const;

    std::filesystem::path path;
    std::ifstream file;

    std::array<uint8_t, ei_nident> ident{};

    std::variant<sections32, sections64> sections;
    std::variant<headers32, headers64> program_headers;
    std::variant<elf32, elf64> elf_header;
    std::variant<dynamic_sections32, dynamic_sections64> dynamic_sections;

    uint8_t bitness{};
};

} // namespace analyzer::posix

#endif
